package framework.classification.entities;

import java.util.ArrayList;

import framework.AnnuaireCocola;
import framework.HierarchyCocola;
import framework.classification.entities.lattice.TreillisI;
import framework.classification.library.AbstractClassfication;
import framework.entity.ACLEntity;
import framework.entity.ACLFunction;
import framework.entity.ACLParameter;

public class ClFunctionRequired extends ClAbstractEntity {

	public static String FUNCTION_REQUIRED = "FunctionRequired"; 


	private ArrayList<ACLFunction> fonctions;
	private ACLFunction funcmodel;
	public ClFunctionRequired(String s, AbstractClassfication cl, TreillisI t,
			ArrayList<ACLFunction> a) {
		super(s, cl, t);

		fonctions = a;
		createTableModel();
		int x = getAttribut().size();
		int y = getEntity().size();
		table = new int[x][y];
		calculPair();
		


	}

	public void createTableModel() {

		funcmodel = new ACLFunction(getName());
		funcmodel.addOut("ANY");


		for (ACLFunction func : fonctions){
			updateFunctionModel(func);
			getEntity().add(func.toString());

			//ajout des parametres d'entrees de la fonction
			for (String para : func.getIn()){


				if (!getAttribut().contains("IN="+para))
					getAttribut().add("IN="+para);

				//on ajoute tous les parametres enfants de parametre
				ArrayList<String> childsPara = getAbstractClassfication().getStructure().getHierarchyDown().get(para);
				for (int i=0;i<childsPara.size();i++){
					String p = childsPara.get(i);
					if (!p.equals("ANY")){
						if (!getAttribut().contains("IN="+p))
							getAttribut().add("IN="+p);
					}

				}
				
				//on ajoute tous les parametres parent de parametre
				ArrayList<String> parentsPara = getAbstractClassfication().getStructure().getHierarchyUp().get(para);
				for (int i=0;i<parentsPara.size();i++){
					String p = parentsPara.get(i);
					if (!p.equals("void")){
						if (!getAttribut().contains("IN="+p))
							getAttribut().add("IN="+p);
					}
				}
			}





			//ajout du parametre de sortie
			if (!getAttribut().contains("OUT="+func.getOut()))
				getAttribut().add("OUT="+func.getOut());

			//on ajoute tous les parametres enfants de parametre
			ArrayList<String> childsPara = getAbstractClassfication().getStructure().getHierarchyDown().get(func.getOut());
			for (int i=0;i<childsPara.size();i++){

				String p = childsPara.get(i);
				if (!p.equals("ANY")){
					if (!getAttribut().contains("OUT="+p))
						getAttribut().add("OUT="+p);
				}
			}

			//on ajoute tous les parametres parent de parametre
			ArrayList<String> parentsPara = getAbstractClassfication().getStructure().getHierarchyUp().get(func.getOut());
			for (int i=0;i<parentsPara.size();i++){
				String p = parentsPara.get(i);
				if (!p.equals("void")){
					if (!getAttribut().contains("OUT="+p))
						getAttribut().add("OUT="+p);
				}
			}



		}



	}

	public void updateFunctionModel(ACLFunction aclfunc){


		ArrayList<String> topsIn = new ArrayList<String>();
		for (String in : aclfunc.getIn()){
			topsIn.add(cl.getStructure().getMaxSuperType(in));
		}
		String topOut = cl.getStructure().getMaxSuperType(aclfunc.getOut());
		funcmodel.getIn().removeAll(topsIn);
		funcmodel.getIn().addAll(0,topsIn);
		if (cl.getStructure().isParent(aclfunc.getOut(),funcmodel.getOut()));
		funcmodel.addOut(topOut);


	}

	protected void calculPair() {

		for (int x = 0; x < this.getAttribut().size(); x++) {
			for (int y = 0; y < this.getEntity().size(); y++) {

				if (isPair(getAttribut().get(x), getEntity().get(y), y))
					table[x][y] = 1;
				else if (table[x][y] == 0)
					table[x][y] = 0;

			}
		}
	}

	protected Boolean isPair(String parametre, String operation, int y) {
		String type = parametre.substring(0, parametre.indexOf("="));
		String para = parametre.substring(parametre.indexOf("=") + 1);

		if (type.equals("IN")){

			//le parametre parametre doit etre parent d'un parametre inclus dans la fonction
			ACLFunction aclfunc = new ACLFunction(operation,ACLFunction.MODE2);
			for (String parafunc : aclfunc.getIn()){
				if (para.equals(parafunc))
					return true;
				if (getAbstractClassfication().getStructure().isParent(para,parafunc))
					return true;
			}
			return false;

		}
		else{
			//le paramatre parametre doit enfant du parametre de sortie de la fonction
			ACLFunction aclfunc = new ACLFunction(operation,ACLFunction.MODE2);
			String parafunc = aclfunc.getOut();
			if (para.equals(parafunc)) 
				return true;
			else if (getAbstractClassfication().getStructure().isParent(parafunc,para))
				return true;
			else return false;
		}

	}

	@Override
	public String getType() {
		// TODO Auto-generated method stub
		return FUNCTION_REQUIRED;
	}

	public ACLFunction getModelIn(){
		return funcmodel;
	}

	@Override
	public ACLEntity getACLEntity(String s) {
		// TODO Auto-generated method stub
		return null;
	}

	


}
